Introduction:
In the first part of this tutorial we saw how to import new funcs. manually and reversing the resource of the target adding a button to it.
In this part of it we will deal with the code injection part where we'll add code to the program to make both, 'Show' and 'Exit' buttons work. To continue with this tutorial you need some experience with locating caves (you may read fornix tutorial "Caving for newbies"), ASM as we're going to write the proper code to make things work (you must be familiar with API funcs.) and ofcourse you should know how to inject a code in a suitable way (you can find alot of resources if you search alil bit for the right thing in the right place).
Tools we'll use:
1- LordPE, or any HEXeditor you like.
2- OllyDbg, or any debugger you like.
Understanding the code flow:
I've included the target (which funcs. have been added to) in this package 'reCuteMessage.zip' just in case you knew how to import and resource manually and wanted to learn about code injection only.
Load the target with Olly, now do right click and choose: Search for -> All intermodular calls, thank GOD there are few funcs. that we should care about, as i look @ the imports i see 'CreateDialogParamA', other message handling funcs. are not that important for our reversing example.. we need now to understand what this func. is used to, so use your win32api manual and search for 'CreateDialogParamA'..
The CreateDialogParam function creates a modeless dialog box from a dialog box
template resource. Before displaying the dialog box, the function passes an
application-defined value to the dialog box procedure as the lParam parameter
of the the WM_INITDIALOG message. An application can use this value to initialize
dialog box controls.
HWND CreateDialogParam(
HINSTANCE hInstance, // handle to application instance
LPCTSTR lpTemplateName, // identifies dialog box template
HWND hWndParent, // handle to owner window
DLGPROC lpDialogFunc, // pointer to dialog box procedure
LPARAM dwInitParam // initialization value
);
if you read the highlighted text in the pretext you see that the lpDialogFunc param handles the messages sent to the dialogbox, under Olly the lpDialogFunc is located @ addr 401103.
after the target process all the MSGs sent to the dialogbox by the 'WM_INITDIALOG' it waits for a MSG sent to the dialog control such as buttons.. the MSG sent to any control in the dialog is handled by the lpDialogFunc param..
CuTedEviL was right, the programmer was lazy to link the code for 'Exit' button!.. So how do we do that for him? The way of doing so is by understanding the lpDialogFunc param to see what's being handled and how..
The problem we have here is there are two buttons so we need to differ between 'em.. to understand this i wrote a small application in MASM with 3 buttons, and started debugging it..
The procedure of the lpDialogFunc param is real simple.. load the file 'test.exe' located in folder 'testme/bin' in this package with Olly (the MD5 signature is: 'BE75C2DAC0DA27F5F5A0DA296418B6D6') then run it with F9. Before you hit any button set a bp on addr 401051, at this addr you make sure that the program recieved a WM_COMMAND MSG and is about to differ between the buttons.. after you hit the 'Show' button for example you will see this
the program recieved a WM_COMMAND MSG and verified that by ignoring the JNZ command, now it's time to tell which button has been clicked, the program use the button 'wParam' which is represented by the control ID to know which button has been clicked, in the previouse picture you see there is a 'CMP AX, 12C' command, the Hex '12C' value is '300' in Decimal (means, the program is checking if the button was the 'Show' button), and because you've clicked that button the program will ignore the JNZ command and continue to display the msgbox on the screen.
feel free to test other buttons, for the 'me' button i didn't write any code so you'll see that the program returns TRUE as well in EAX.
now how can we use such information with our target file?
Let's first take a note of the controls IDs, 'Exit ID=1001, Show ID=1004, textbox ID = 1002' (you can simply do that with any resource editor or from your HEXeditor). Now load the target with Olly, press F9 to run it, now scroll down in the CPU menu 'till you reach the check of the WM_COMMAND MSG @ addr 40111B, set a bp on addr 401122 to make sure it's a WM_COMMAND MSG, we'll test what we have learned with this one so hit the 'Exit' button and you should break in Olly, this is what you'll see
the 'MOV EAX, DWORD PTR [EBP+10]' command copies the wParam of the button to EAX, then EAX is compared with the value '2711' which equals '10001' in Decimal, you see also that there is a 'SendMessageA' func. with a WM_CLOSE MSG is about to be sent to the dialog upon that comparation so, to fix the 'Exit' button we need only to change the value '2711' into the ID of the 'Exit' button which is '1001' and it equals '3E9' in Hex.. yes, I know, I didn't forget about the 'Show' button so this is what we are going to do..
1- redirect the flow somewhere
2- inject our code in that place to be executed
3- and return to normal flow
Cave sweet Cave!
For the cave we will choose addr = 402340, now we have to redirect the flow to that cave.. tnx CuTedEviL for those 5 bytes you left us for the JMP, I owe you one :)
We will replace the 'AND' command you see in the previouse picture (after the JNZ of the WM_COMMAND compare) with a JMP to the addr we choosed, so replace 'AND EAX, 0FFFF' with 'JMP 402340' and hit enter to go there.
Now we'll insert a code that checks if the clicked button was 'Exit' or 'Show'.. because the program already copied the button ID to EAX we will simply start with a CMP to check the ID.. but before that you should know that we'll need the names of 'GetDlgItemTextA' and 'MessageBoxA' funcs... that can be done with LordPE @ some addr you choose something like shown in the picture below
now the whole code you need is this..
cmp eax, 3ec ; compare the ID with 3EC = 'Show'
jne 40112a ; it's not so go back to normal flow
; now the 'Show' button should display what's in the textbox
push 40221c ; push lib name
call LoadLibraryA ; get handle of 'user32.dll'
mov edi, 4023a0 ; put addr 4023a0 in EDI
mov dword ptr [edi], eax ; save lib handle for l8r use
push 4023e0 ; push func. name 'GetDlgItemTextA'
push dword ptr [edi] ; push it to the stack
call GetProcAddress ; get func. addr
push 14 ; max size of text to get '20'
push 4023c3 ; buffer addr
push 3ea ; textbox ID
push dword ptr [ebp+8] ; dialog handle
call eax ; call GetDlgItemTextA
test eax, eax ; nothing entered?
jz 402399 ; then don't display a thing
push 4023d4 ; push func. name 'MessageBoxA'
push dword ptr [edi] ; push lib handle
call GetProcAddress ; and get the func. addr
push 0 ; msg type
push 4023f0 ; caption
push 4023c3 ; text
push 0 ; window handle
call eax ; call MessageBoxA
402399:
jmp 401170 ; go back to main procedure
after you write this code in Olly CPU window you can copy it directly to the .exe without any need for HEX editing again, just highlight all the codes, do right click and choose 'Copy to executable -> Selection', now close the new window that appeared and save the changes you've made to the same file 'reCuteMessage.exe'..
few things you have to do now in order to finish this mission, you've to save also the changes you've made to the 'AND' command as we don't need it anymore (it doesn't affect the behaviour of the target), do the same with it 'Copy to executable -> Selection' and save it.
last but not least, if you read the code you see that we're checking if the button was 'Show' using the ID and if it's not then we redirect the flow back to normal to check if it a button with an ID '10001', now because we know it should be the 'Exit' then also patch that ID from '2711' into '3e9' and save the changes.
test the changes you have made and unfortunately you'll see the program crashs.. why? that's because your code is attempting to write some values in a section that doesn't have the 'Write' flag, so just use LordPE and edit the characterstics of the '.rdata' section into 'C0000040' and you're done.. let's hope it works under other OSs! :p
Final notes:
This part of the tutorial wasn't that long and i think it's too simple to understand it.. I just wanna give you a tip.. when your trying to reverse something like crippled targets or stuff like that, it's a good idea to write a simple target that uses the funcs. you are dealing with and check what's different between the two targets.
Greetings:
I'de like to send my greets to Fusion members for being there, and to all i've sent my greetings before (I'm lazy to write your names again :)
Xacker of Fusion - peaCe